#define LG_CORE

#include "lg_std.h"

static LGVertexAttr STD_VERTEX_ATTRS[] = {
	{LG_VERTEX_POSITION, LG_VERTEX_OFFSET(LGStdPoint, position)},
	{LG_VERTEX_COLOR, LG_VERTEX_OFFSET(LGStdPoint, color)},
	{LG_VERTEX_UV, LG_VERTEX_OFFSET(LGStdPoint, uv)},
	{LG_VERTEX_NORMAL, LG_VERTEX_OFFSET(LGStdPoint, normal)},
};

static struct {
	LGConfig* config;
	LGStdBackend* backend;
}ctx = { 0 };

LG_API int
lgInitStdContext(LGConfig* config, LGStdBackend* backend) {
	ctx.config = config;
	ctx.backend = backend;
	return 0;
}

LG_API LGShader*
lgNewStdShader(LGStdShader e) {
	return ctx.backend->stdShader(e);
}

LG_API const char**
lgStdShaderSource(LGStdShader e) {
	return ctx.backend->stdShaderSource(e);
}

LG_API LGVertex*
lgNewStdVertex(unsigned cap) {
	return lgNewVertex(
		STD_VERTEX_ATTRS, 4, sizeof(LGStdPoint), cap);
}

LG_API unsigned
lgPushStdVertexRect(LGVertex* vertex, LGVector* size,
	LGVector* color, unsigned indexOffset, LGMatrix* transform) {
	LGFloat x = size->x * 0.5f;
	LGFloat y = size->y * 0.5f;
	LGStdPoint vs[] = {
		{
			{ -x, y, 0.f, 1.f}, *color,
			{0.f, 0.f, 0.f, 0.f}, {0.f, 0.f, 1.f, 1.f},
		},
		{
			{x, y, 0.f, 1.f}, *color,
			{1.f, 0.f, 0.f, 0.f}, {0.f, 0.f, 1.f, 1.f},
		},
		{
			{-x, -y, 0.f, 1.f},  *color,
			{0.f, 1.f, 0.f, 0.f}, {0.f, 0.f, 1.f, 1.f},
		},
		{
			{x, -y, 0.f, 1.f}, *color,
			{1.f, 1.f, 0.f, 0.f}, {0.f, 0.f, 1.f, 1.f},
		},
	};
	unsigned indexs[] = { 0, 1, 2, 1, 2, 3 };
	if (transform) {
		for (unsigned i = 0; i < 4; i++) {
			lgVectorMulMatrix(&vs[i].position, transform);
		}
	}
	for (unsigned i = 0; i < 6; i++) {
		indexs[i] += indexOffset;
	}
	lgPushVertexData(vertex, vs, 4);
	lgPushVertexIndexs(vertex, indexs, 6);
	return 6;
}


LG_API unsigned
lgPushStdVertexBox(LGVertex* vertex, LGVector* size,
	LGVector* color, unsigned indexOffset, LGMatrix* transform) {
	LGFloat x = size->x * 0.5f;
	LGFloat y = size->y * 0.5f;
	LGFloat z = size->y * 0.5f;
	LGStdPoint vs[] = {
		{
			{-x, -y, z, 1.f},  *color,
			{0.f, 0.f, 0.f, 0.f}, {0.f, 0.f, 1.f, 1.f},
		},
		{
			{x, -y, z, 1.f}, *color,
			{0.f, 1.f, 0.f, 0.f}, {0.f, 0.f, 1.f, 1.f},
		},
		{
			{ -x, y, z, 1.f}, *color,
			{1.f, 0.f, 0.f, 0.f}, {0.f, 0.f, 1.f, 1.f},
		},
		{
			{x, y, z, 1.f}, *color,
			{1.f, 1.f, 0.f, 0.f}, {0.f, 0.f, 1.f, 1.f},
		},
				{
			{-x, -y, -z, 1.f},  *color,
			{0.f, 0.f, 0.f, 0.f}, {0.f, 0.f, 1.f, 1.f},
		},
		{
			{x, -y, -z, 1.f}, *color,
			{0.f, 1.f, 0.f, 0.f}, {0.f, 0.f, 1.f, 1.f},
		},
		{
			{ -x, y, -z, 1.f}, *color,
			{1.f, 0.f, 0.f, 0.f}, {0.f, 0.f, 1.f, 1.f},
		},
		{
			{x, y, -z, 1.f}, *color,
			{1.f, 1.f, 0.f, 0.f}, {0.f, 0.f, 1.f, 1.f},
		},
	};	
	unsigned indexs[] = {
		0, 1, 2, 1, 2, 3,
		4, 5, 6, 5, 6, 7,
		0, 4, 5, 0, 1, 5,
		0, 2, 4, 2, 4, 6,
		2, 3, 6, 3, 6, 7,
		1, 3, 5, 3, 5, 7,
	};
	if (transform) {
		for (unsigned i = 0; i < 8; i++) {
			lgVectorMulMatrix(&vs[i].position, transform);
		}
	}
	for (unsigned i = 0; i < 36; i++) {
		indexs[i] += indexOffset;
	}
	lgPushVertexData(vertex, vs, 8);
	lgPushVertexIndexs(vertex, indexs, 36);
	return 36;
}
